﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using SyringeControl.AssemblySelectors;
using SyringeControl.Factories;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Castle.MicroKernel.Registration;
using Castle.Windsor.Adapters.ComponentModel;
using SyringeControl.ControlConfiguration.Events;
using SyringeControl.ControlConfiguration;
using System.Drawing;
//using System.ComponentModel;

namespace SyringeControl
{
    class SyringeContainer : WindsorContainer
    {
        public static readonly SyringeContainer Instance = new SyringeContainer();

        private SyringeContainer()
            : base(new XmlInterpreter())
        {

        }
    }

    class Program
    {
        bool showUsage;
        string assemblyPath;
        string controlTypeName;
        SyringeContainer container;
        public Program(string[] args)
        {
            container = SyringeContainer.Instance;
            Application.ThreadException += Application_ThreadException;
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Trace.WriteLine(new string('-', 70));

            ParseArgs(args);
        }

        private void ParseArgs(string[] args)
        {
            for (var argsIter = (args as IList<string>).GetEnumerator(); argsIter.MoveNext(); )
            {
                switch (argsIter.Current)
                {
                    case "-help": 
                    case "-h":
                    case "-usage": showUsage = true; break;
                    case "-t": argsIter.MoveNext(); controlTypeName = argsIter.Current; break;
                    default: assemblyPath = argsIter.Current; break;
                }
            }
        }

        class MySite : IContainerAdapterSite
        {
            IContainerAdapter _adapter;
            public MySite(IContainerAdapter adapter)
            {
                _adapter = adapter;
                Container = adapter;
            }

            #region Члены ISite

            public System.ComponentModel.IComponent Component
            {
                get;
                private set;
            }

            public System.ComponentModel.IContainer Container
            {
                get;
                private set;
            }

            public bool DesignMode
            {
                get { return false; }
            }

            public string Name
            {
                get;
                set;
            }

            #endregion

            #region Члены IServiceProvider

            public object GetService(Type serviceType)
            {
                return _adapter.GetService(serviceType);
            }

            #endregion
        
            #region Члены IContainerAdapterSite

            public string  EffectiveName
            {
	            get { throw new NotImplementedException(); }
            }

            #endregion
        }

        public ApplicationContext CreateContext()
        {
            container.Register(new IRegistration[]{
                Component.For<IContainerAdapter>().ImplementedBy<ContainerAdapter>(),
                Component.For<System.ComponentModel.ISite>().ImplementedBy<MySite>(),
                Component.For<IAssemblySelector>().ImplementedBy<OpenFileAssemblySelector>(),
                Component.For<IViewControlModel>().ImplementedBy<ViewControlModel>()
                    .DependsOn(Property.ForKey("Container")),
                Component.For<Form,IControlView>().ImplementedBy<MainForm>(),
                Component.For<IControlFactory>().ImplementedBy<ActivatorControlFactory>(),
                Component.For<MainFormController>().ImplementedBy<MainFormController>(),
                Component.For<ApplicationContext>().ImplementedBy<SyringeContext>(),
                Component.For<IAdapterBuilder>().ImplementedBy<GenericEventHandlerAdapterFactory>(),
                Component.For<IEventLoggingSettingsProvider>().ImplementedBy<DefaultEventSettingsProvider>(),
                Component.For<IEventLogger>().ImplementedBy<NullEventLogger>().Named("none"),
                Component.For<IEventLogger>().ImplementedBy<MessageBoxEventLogger>().Named("messageBox"),
                Component.For<IEventLogger>().ImplementedBy<TraceEventLogger>().Named("trace"),
            });
            var controller = container.Resolve<MainFormController>();
            var context = container.Resolve<ApplicationContext>();
            if (!String.IsNullOrEmpty(assemblyPath) && !String.IsNullOrEmpty(controlTypeName))
                context.MainForm.Load += delegate
                {
                    controller.SetAssemblyAndType(assemblyPath, controlTypeName);
                };
            return context;
        }

        public void Run()
        {
            if (showUsage)
                MessageBox.Show(
@"usage: SyringeControl.exe -help | -t [typename] [assemblyPath]
  -help                     this message
  [typename]                type of control to test
  [assemblyPath]            path to assembly to load type from
", "Help", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            else
                Application.Run(CreateContext());
        }

        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            var program = new Program(args);
            program.Run();
        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            Trace.WriteLine("Exception was not handled: " + e.Exception);
            MessageBox.Show("UnhandledException: " + e.Exception, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1,
                    MessageBoxOptions.DefaultDesktopOnly);
        }

    }
}
